<?php

/* @project : Template
 * @auther  : 青云
 * @date    : 2018/1/10
 * @desc    : 目的地模型
 */

namespace app\common\model;

use EasyWeChat\Factory;

class Weixin extends Base
{

    private $appid;
    private $sessionKey;
    public static $OK = 0;
    public static $IllegalAesKey = -41001;
    public static $IllegalIv = -41002;
    public static $IllegalBuffer = -41003;
    public static $DecodeBase64Error = -41004;

    /**
     * 构造函数
     * @param $sessionKey string 用户在小程序登录后获取的会话密钥
     * @param $appid string 小程序的appid
     */
    public function __construct( $appid, $sessionKey)
    {
        $this->sessionKey = $sessionKey;
        $this->appid = $appid;
    }

    function send($openid, $data, $template_id, $url = '')
    {
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'response_type' => 'array',
            'key' => get_system_config('weixin_key', 'weixin'),
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $app = Factory::officialAccount($config);

        $option['touser'] = $openid;
        $option['template_id'] = $template_id;
        $option['url'] = $url;
        $option['data'] = $data;
        try {
            @$ret = $app->template_message->send($option);
        } catch (Exception $e) {
            echo '错误：' . $e->getMessage();
        }
    }

    function unifyOrder($title, $order_no, $amount, $openid)
    {
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'mch_id' => get_system_config('weixin_mch_id', 'weixin'),
            'key' => get_system_config('weixin_key', 'weixin'),
            'response_type' => 'array',
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $app = Factory::payment($config);

        $result = $app->order->unify([
            'body' => $title,
            'out_trade_no' => $order_no,
            'total_fee' => $amount,
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => $openid,
        ]);

        // APP
        $config = $this->app($result['prepay_id']);

        // JSSDK
        //$config = $this->jssdk($result['prepay_id']);

        // H5
        //$config = $this->bridge($result['prepay_id']);

        return $config;
    }

    // JSSDK
    function jssdk($prepay_id)
    {
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'response_type' => 'array',
            'key' => get_system_config('weixin_key', 'weixin'),
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $payment = Factory::payment($config);

        $jssdk = $payment->jssdk;

        $config = $jssdk->sdkConfig($prepay_id); // 返回数组

        return $config;
    }

    // H5 支付
    function bridge($prepay_id)
    {
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'response_type' => 'array',
            'key' => get_system_config('weixin_key', 'weixin'),
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $payment = Factory::payment($config);

        $jssdk = $payment->jssdk;

        $json = $jssdk->bridgeConfig($prepay_id);

        return $json;
    }


    // APP支付

    function app($prepay_id)
    {
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'response_type' => 'array',
            'key' => get_system_config('weixin_key', 'weixin'),
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $payment = Factory::payment($config);

        $jssdk = $payment->jssdk;
        $config = $jssdk->appConfig($prepay_id);
        return $config;
    }


    /*
     * 企业付款到用户零钱
     * User:剑圣
     * Date:2020/3/19
     * Time:22:48
     * @param
     * $order_no订单号
     * $openid   微信openid
     * $re_user_name  用户真实姓名
     * $amount  付款金额
     * $desc 说明
     * */
    public function toBalance($order_no, $openid, $re_user_name, $amount, $desc){
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'response_type' => 'array',
            'key' => get_system_config('weixin_key', 'weixin'),
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $app = Factory::officialAccount($config);
        $result = $app->transfer->toBalance([
            'partner_trade_no' => $order_no, // 商户订单号，需保持唯一性(只能是字母或者数字，不能包含有符号)
            'openid' => $openid,
            'check_name' => 'FORCE_CHECK', // NO_CHECK：不校验真实姓名, FORCE_CHECK：强校验真实姓名
            're_user_name' => $re_user_name, // 如果 check_name 设置为FORCE_CHECK，则必填用户真实姓名
            'amount' => $amount, // 企业付款金额，单位为分
            'desc' => $desc, // 企业付款操作说明信息。必填
        ]);
        return $result;
    }

    /*
     * 查询企业付款到用户零钱是否到账
     * User:剑圣
     * Date:2020/3/19
     * Time:23:18
     * @param
     * $order_no订单号
     * */
    public function queryBalance($order_no)
    {
        $config = [
            'app_id' => get_system_config('weixin_app_id', 'weixin'),
            'secret' => get_system_config('weixin_secret', 'weixin'),
            'response_type' => 'array',
            'key' => get_system_config('weixin_key', 'weixin'),
            'cert_path' => 'path/to/your/cert.pem', // XXX: 绝对路径！！！！
            'key_path' => 'path/to/your/key',      // XXX: 绝对路径！！！！
            'notify_url' => url('api/weixin/notify'),     // 你也可以在下单时单独设置来想覆盖它
        ];

        $app = Factory::officialAccount($config);
        $result = $app->transfer->queryBalanceOrder($order_no);
        return $result;
    }


    /**
     * 检验数据的真实性，并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0，失败返回对应的错误码
     */
    public function decryptData( $encryptedData, $iv, &$data )
    {
        if (strlen($this->sessionKey) != 24) {
            return self::$IllegalAesKey;
        }
        $aesKey=base64_decode($this->sessionKey);

        
        if (strlen($iv) != 24) {
            return self::$IllegalIv;
        }
        $aesIV=base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

        $dataObj=json_decode( $result );
        if( $dataObj  == NULL )
        {
            return self::$IllegalBuffer;
        }
        if( $dataObj->watermark->appid != $this->appid )
        {
            return self::$IllegalBuffer;
        }
        $data = $result;
        return self::$OK;
    }

}
